package com.pulse.common.utils.sor;

import com.pulse.common.utils.sor.domain.Block;
import com.pulse.common.utils.sor.domain.GenParamsVo;
import com.pulse.common.utils.sor.domain.SorInfo;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

public class GenParams {

    /**
     * 处理 GenParams 块
     *
     * @param fh      输入流
     * @param sorInfo 存储结果的对象
     * @return 状态字符串
     */
    public static String process(BufferedInputStream fh, SorInfo sorInfo) {

        final String bname = "GenParams";
        int hsize = bname.length() + 1;  // 包括尾部的 '\0'
        Block refBlock = null;
        String status = "nok";

        try {
            refBlock = sorInfo.getBlocks().getGenParams();
            long startpos = (long) refBlock.getPos();
            fh.reset();
            fh.skip(startpos);  // 跳过块的起始位置
        } catch (Exception ex) {
            return status;
        }

        int format = sorInfo.getFormat();

        if (format == 2) {
            byte[] buffer = new byte[hsize];
            try{
                fh.read(buffer, 0, hsize);
            }catch (IOException e){
                return "nok";
            }
            String mystr = new String(buffer, StandardCharsets.US_ASCII);
            if (!mystr.equals(bname + "\0")) {
                return status;
            }
        }

        sorInfo.setGenParams(new GenParamsVo());

        try{
            if (format == 1) {
                status = process1(fh, sorInfo);
            } else {
                status = process2(fh, sorInfo);
            }
        }catch (Exception e){
            return "nok";
        }

        return status;
    }

    /**
     * 处理版本 1 格式
     */
    private static String process1(InputStream fh, SorInfo sorInfo) throws IOException {
        final String bname = "GenParams";
        GenParamsVo xref = sorInfo.getGenParams();

        byte[] langBuffer = new byte[2];
        fh.read(langBuffer, 0, 2);
        String lang = new String(langBuffer, StandardCharsets.US_ASCII);
        xref.setLanguage(lang);

        String[] fields = {
                "cable ID", // ........... 0
                "fiber ID", // ........... 1
                "wavelength", // ............2: fixed 2 bytes value
                "location A", // ............ 3
                "location B", // ............ 4
                "cable code/fiber type", // ............ 5
                "build condition", // ....... 6: fixed 2 bytes char/string
                "user offset", // ........... 7: fixed 4 bytes (Andrew Jones)
                "operator", // ........... 8
                "comments", // ........... 9
        };

        for (String field : fields) {
            String xstr;
            if (field.equals("build condition")) {
                byte[] bcBuffer = new byte[2];
                fh.read(bcBuffer, 0, 2);
                xstr = buildCondition(new String(bcBuffer, StandardCharsets.US_ASCII));
            } else if (field.equals("wavelength")) {
                int val = (int) Parts.getUInt(fh, 2);
                xstr = val + " nm";
            } else if (field.equals("user offset")) {
                int val = (int) Parts.getSigned(fh, 4);
                xstr = String.valueOf(val);
            } else {
                xstr = Parts.getString(fh);
            }

            switch (field){
                case "cable ID":
                    xref.setCableID(xstr);
                    break;
                case "fiber ID":
                    xref.setCableID(xstr);
                    break;
                case "wavelength":
                    xref.setWavelength(xstr);
                    break;
                case "location A":
                    xref.setLocationA(xstr);
                    break;
                case "location B":
                    xref.setLocationB(xstr);
                    break;
                case "cable code/fiber type":
                    xref.setCableCodeOrFiberType(xstr);
                    break;
                case "build condition":
                    xref.setBuildCondition(xstr);
                    break;
                case  "user offset":
                    xref.setUserOffset(xstr);
                    break;
                case "operator":
                    xref.setOperator(xstr);
                    break;
                case "comments":
                    xref.setComments(xstr);
                    break;
                default:
                    break;
            }

        }

        return "ok";
    }

    /**
     * 处理版本 2 格式
     */
    private static String process2(InputStream fh, SorInfo sorInfo) throws IOException {
        final String bname = "GenParams";
        GenParamsVo xref = sorInfo.getGenParams();

        byte[] langBuffer = new byte[2];
        fh.read(langBuffer, 0, 2);
        String lang = new String(langBuffer, StandardCharsets.US_ASCII);
        xref.setLanguage(lang);

        String[] fields = {
                "cable ID", // ........... 0
                "fiber ID", // ........... 1
                "fiber type", // ........... 2: fixed 2 bytes value
                "wavelength", // ............3: fixed 2 bytes value
                "location A", // ............ 4
                "location B", // ............ 5
                "cable code/fiber type", // ............ 6
                "build condition", // ....... 7: fixed 2 bytes char/string
                "user offset", // ........... 8: fixed 4 bytes int (Andrew Jones)
                "user offset distance", // .. 9: fixed 4 bytes int (Andrew Jones)
                "operator", // ........... 10
                "comments", // ........... 11
        };

        for (String field : fields) {
            String xstr;
            if (field.equals("build condition")) {
                byte[] bcBuffer = new byte[2];
                fh.read(bcBuffer, 0, 2);
                xstr = buildCondition(new String(bcBuffer, StandardCharsets.US_ASCII));
            } else if (field.equals("fiber type")) {
                int val = (int) Parts.getUInt(fh, 2);
                xstr = fiberType(val);
            } else if (field.equals("wavelength")) {
                int val = (int) Parts.getUInt(fh, 2);
                xstr = val + " nm";
            } else if (field.equals("user offset") || field.equals("user offset distance")) {
                int val = (int) Parts.getSigned(fh, 4);
                xstr = String.valueOf(val);
            } else {
                xstr = Parts.getString(fh);
            }

            switch (field){
                case "cable ID":
                    xref.setCableID(xstr);
                    break;
                case "fiber ID":
                    xref.setCableID(xstr);
                    break;
                case "fiber type":
                    xref.setFiberType(xstr);
                    break;
                case "wavelength":
                    xref.setWavelength(xstr);
                    break;
                case "location A":
                    xref.setLocationA(xstr);
                    break;
                case "location B":
                    xref.setLocationB(xstr);
                    break;
                case "cable code/fiber type":
                    xref.setCableCodeOrFiberType(xstr);
                    break;
                case "build condition":
                    xref.setBuildCondition(xstr);
                    break;
                case  "user offset":
                    xref.setUserOffset(xstr);
                    break;
                case "user offset distance":
                    xref.setUserOffsetDistance(xstr);
                    break;
                case "operator":
                    xref.setOperator(xstr);
                    break;
                case "comments":
                    xref.setComments(xstr);
                    break;
                default:
                    break;
            }
        }

        return "ok";
    }

    /**
     * 解码构建条件
     */
    private static String buildCondition(String bcstr) {
        switch (bcstr) {
            case "BC":
                return bcstr + " (as-built)";
            case "CC":
                return bcstr + " (as-current)";
            case "RC":
                return bcstr + " (as-repaired)";
            case "OT":
                return bcstr + " (other)";
            default:
                return bcstr + " (unknown)";
        }
    }

    /**
     * 解码光纤类型
     */
    private static String fiberType(int val) {
        switch (val) {
            case 651:
                return "G.651 (50um core multimode)";
            case 652:
                return "G.652 (standard SMF)";
            case 653:
                return "G.653 (dispersion-shifted fiber)";
            case 654:
                return "G.654 (1550nm loss-minimzed fiber)";
            case 655:
                return "G.655 (nonzero dispersion-shifted fiber)";
            default:
                return val + " (unknown)";
        }
    }
}
